﻿using FasterWPF;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

namespace WPFContrib
{
    public class SimplePagingControl
    {
        private int _startInt = 0;
        private int _totalInt = 0;
        private double _leftMargin = 0.0D;
        private double _topMargin = 0.0D;
        private int _recordsInPage = 0;
        private Border _startNumBorder = null;
        private Border _totalNumBorder = null;
        private Border _previousBorder = null;
        private Border _nextBorder = null;
        private StackPanel _pagingControl = null;
        private Action<DataGrid, int, int> _loadDataPageNext = null;
        private Action<DataGrid, int, int> _loadDataPagePrev = null;
        private DataGrid _mainDataGrid = new DataGrid();
        private List<string> _columnHeaderList = null;
        private Label _titleLabel = null;
        private string  _title= null;
        private Action<SimplePagingControl, StackPanel> _firePagePrevious = (splPagingCtrl, stkPanel) => { splPagingCtrl.ChangePage(stkPanel, false); };
        private Action<SimplePagingControl, StackPanel> _firePageNext = (splPagingCtrl, stkPanel) => { splPagingCtrl.ChangePage(stkPanel, true); };

        public Label TitleLabel
        {
            get { return _titleLabel; }
            set { _titleLabel = value; }
        }

        public double LeftMargin
        {
            get { return _leftMargin; }
            set { _leftMargin = value; }
        }

        public double TopMargin
        {
            get { return _topMargin; }
            set { _topMargin = value; }
        }

        public Border PreviousButton
        {
            get { return _previousBorder.GetChildFromComposite<Border, StackPanel>(0, 1); }
        }

        public Border NextButton
        {
            get { return _nextBorder.GetChildFromComposite<Border, StackPanel>(0, 1); }
        }

        public Action<SimplePagingControl, StackPanel> PreviousButtonSingleClick
        {
            get
            {
                return _firePagePrevious; 
            }
        }

        public Action<SimplePagingControl, StackPanel> NextButtonSingleClick
        {
            get
            {
                return _firePageNext;
            }
        }

        public List<string> ColumnHeaderList
        {
            get { return _columnHeaderList; }
            set { _columnHeaderList = value; }
        }

        public DataGrid MainDataGrid
        {
            get { return _mainDataGrid; }
            set { _mainDataGrid = value; }
        }

        public Action<DataGrid, int, int> LoadDataPageNext
        {
            get { return _loadDataPageNext; }
            set { _loadDataPageNext = value; }
        }

        public Action<DataGrid, int, int> LoadDataPagePrev
        {
            get { return _loadDataPagePrev; }
            set { _loadDataPagePrev = value; }
        }

        public SimplePagingControl(double leftMargin, double topMargin, string title) 
        {
            _leftMargin = leftMargin;
            _topMargin = topMargin;
            _title = title;
        }

        public int DivideTotalRecordsAlwaysRoundingUp(long totalRecords, int recordsInPage)
        {
            return (int)Math.Ceiling((double.Parse(((decimal)totalRecords / (decimal)recordsInPage).ToString())));
        }

        public StackPanel BuildDataGridInStackPanel(double width, double height, List<string> columnHeaderList, StackPanel pagingControl)
        {
            var container = new StackPanel();
            container.Initialize(width + _leftMargin, height + 30.0D, ContainerType.ContentControlPanel, Orientation.Vertical);
            container.BeginSettings<StackPanel>()
                 .Set<DataGrid, StackPanel>(0, 0, "Margin", new Thickness(_leftMargin, _topMargin, 0.0, 0.0))
                 .Set<Label, StackPanel>(0, 0, "Margin", new Thickness(_leftMargin, _topMargin, 0.0, 0.0))
                 .EndSettings<StackPanel>();

            _mainDataGrid.Initialize(width, height - 30.0D, ContainerType.VerticalPanel, Brushes.WhiteSmoke, Brushes.Gray, Brushes.Gray, new Thickness(0.0));

            FasterWPF.SettingsManager.BeginSettings<DataGrid>(_mainDataGrid)
               .SetBackgroundColorOnItemsControl(Brushes.LightSlateGray)
               .SetItemBorderColorAndThickness(Brushes.LightGreen, new Thickness(0.0))
               .Set<TextBlock, DataGrid>("Padding", new Thickness(2.0,0.0,2.0,0.0))
               .SetTextColor(0, 1, Brushes.Black)
               .Set<TextBlock, DataGrid>(0, 0, "Margin", new Thickness(3.0,3.0,3.0,1.0))
               .Set<TextBlock, DataGrid>(0, 1, "Margin", new Thickness(3.0,0.0,3.0,1.0))
               .Set<TextBlock, DataGrid>(0, 2, "Margin", new Thickness(3.0,0.0,3.0,3.0))
               .EndSettings();

             _mainDataGrid.BorderBrush=Brushes.Black;
             _mainDataGrid.BorderThickness=new Thickness(0.0); 
        
             ScrollViewerStyle.ApplyToScrollViewer(_mainDataGrid, "LightGreen", "Green", "DarkGreen");

             _columnHeaderList = columnHeaderList;

             _mainDataGrid.ApplyDataGridStrategy(20.0, DataGridSelectionMode.Single, DataGridSelectionUnit.FullRow, Brushes.White, Brushes.LightGreen, Brushes.Black, Brushes.LightGreen, "Gray", "Silver", "1,1,1,1", 1.0, "Gray", "LightGreen", "LightGreen", "LightGreen", "LightGreen");

             Border labelComposite = container.BeginComposite().AddLabel(0, 0, _title, Brushes.Gray).EndComposite(new CanvasArgs(0, 0, 1));
             _titleLabel = labelComposite.GetChildFromComposite<Label, StackPanel>(0, 0);

             container.BeginComposite()
                 .AddExisting<DataGrid, StackPanel>(0, 0, _mainDataGrid)
                 .EndComposite(new StackPanelArgs(Orientation.Vertical));

             container.BeginComposite()
                 .AddExisting<StackPanel, StackPanel>(0, 0, pagingControl)
                 .EndComposite(new StackPanelArgs(Orientation.Vertical));

             return container;
        }

        public StackPanel BuildPagingControl(double width, double height, int pageTotal, int recordsInPage, Action<DataGrid, int, int> loadDataPageNext, Action<DataGrid, int, int> loadDataPagePrev)
        {
            _startInt = 1;
            _totalInt = pageTotal;
            _recordsInPage = recordsInPage;
            _loadDataPageNext = loadDataPageNext;
            _loadDataPagePrev = loadDataPagePrev;

            _pagingControl = new StackPanel();
            _pagingControl.Initialize(width, height, ContainerType.ContentControlPanel, Orientation.Horizontal);
            _pagingControl.Background = Brushes.Beige;

            //No Settings Implemented. 
            //pagingControl.BeginSettings()
            //    .Set<TextBlock, StackPanel>(0, 0, "Margin", new Thickness(13.0, 0.0, 0.0, 0.0))
            //    .EndSettings();

            var bdr1 = _pagingControl.BeginComposite()
                .AddText(0, 0, "Page: ")                
                .EndComposite(new StackPanelArgs(Orientation.Horizontal));

            FasterWPF.CommonExt.UpdateByKey<TextBlock, StackPanel>(_pagingControl, bdr1.GetKey(), 0, 0, txtBlck => txtBlck.Margin = new Thickness(_leftMargin, 0.0, 0.0, 0.0));
            
            _startNumBorder = _pagingControl.BeginComposite()
                .AddText(0, 0, "1 ")
                .EndComposite(new StackPanelArgs(Orientation.Horizontal));

            _pagingControl.BeginComposite()
                .AddText(0, 0, "of ")
                .EndComposite(new StackPanelArgs(Orientation.Horizontal));

            _totalNumBorder = _pagingControl.BeginComposite()
                .AddText(0, 0, pageTotal.ToString())
                .EndComposite(new StackPanelArgs(Orientation.Horizontal));

            var bdr2 = _pagingControl.BeginComposite()
                .AddText(0, 0, "")
                .EndComposite(new StackPanelArgs(Orientation.Horizontal));

            FasterWPF.CommonExt.UpdateByKey<TextBlock, StackPanel>(_pagingControl, bdr2.GetKey(), 0, 0, txtBlck => txtBlck.Width = 373.0);

            var before = FontExt.CreateFont("Segoe UI", 11.0, FontWeights.Bold, FontStyles.Normal);
            var after = FontExt.CreateFont("Segoe UI", 12.0, FontWeights.ExtraBold, FontStyles.Normal);

            _previousBorder = _pagingControl.BeginComposite()
                 .AddFlatButton(0, 1, 58.0, 34.0, "Previous", Brushes.Beige, new Thickness(0.0), Brushes.Beige, new CornerRadius(1.0), new Thickness(3.0,3.0,3.0,2.0), new Thickness(0.0), Brushes.Beige, Brushes.Black, Brushes.Gray, before, after,  new Action<Object, MouseButtonEventArgs>((o,ev)=>
                 {
                          _firePagePrevious(this, _pagingControl);
                 })) 
                .EndComposite(new StackPanelArgs(Orientation.Horizontal));

            _nextBorder = _pagingControl.BeginComposite()
                 .AddFlatButton(0, 1, 50.0, 34.0, "Next", Brushes.Beige, new Thickness(0.0), Brushes.Beige, new CornerRadius(1.0), new Thickness(3.0, 3.0, 3.0, 2.0), new Thickness(0.0), Brushes.Beige, Brushes.Black, Brushes.Gray, before, after, new Action<Object, MouseButtonEventArgs>((o, ev) =>
                 {
                        _firePageNext(this, _pagingControl);
                 })) 
                .EndComposite(new StackPanelArgs(Orientation.Horizontal));

            return _pagingControl;
        }

        public int GetStartNumber()
        {
            return Int32.Parse(FasterWPF.CommonExt.GetChildFromComposite<TextBlock, StackPanel>(_startNumBorder, 0, 0).GetText());
        }

        public int GetTotalNumber()
        {
            return Int32.Parse(FasterWPF.CommonExt.GetChildFromComposite<TextBlock, StackPanel>(_totalNumBorder, 0, 0).GetText());
        }

        public void UpdateStartNumber(int number)
        {
            FasterWPF.CommonExt.UpdateByKey<TextBlock, StackPanel>(_pagingControl, _startNumBorder.GetKey(), 0, 0, txtBlck => FasterWPF.TextBlockExt.SetText(txtBlck, number.ToString() + " "));
        }

        public void UpdateTotalNumber(int number)
        {
            FasterWPF.CommonExt.UpdateByKey<TextBlock, StackPanel>(_pagingControl, _totalNumBorder.GetKey(), 0, 0, txtBlck => FasterWPF.TextBlockExt.SetText(txtBlck, number.ToString() + " "));
        }
        
        public void ChangePage(StackPanel pagingControl, bool shouldPageForward)
        {
            if (!(_startInt == 1 && shouldPageForward == false) && !((_startInt==_totalInt) && shouldPageForward == true))
            {
                if(shouldPageForward)
                {
                    UpdateStartNumber(_startInt + 1);
                    _loadDataPageNext(_mainDataGrid, ((_startInt + 1) * _recordsInPage) - _recordsInPage, (_startInt + 1) * _recordsInPage);
                    _startInt = _startInt + 1;
                }
                else
                {
                    UpdateStartNumber(_startInt - 1);
                    _loadDataPagePrev(_mainDataGrid, ((_startInt - 1) * _recordsInPage) - _recordsInPage, (_startInt - 1) * _recordsInPage);
                    _startInt = _startInt - 1;
                }
            }
            else
            {
                if (_startInt == 1 && shouldPageForward==false)
                {
                    MessageBox.Show("You can't page previous. You are already at the beginning!");
                }
                else
                {
                    MessageBox.Show("You can't page forward. You are already at the end!");
                }
            }
        }
    }
}
